import { AutoComplete, Icon, Input } from 'antd';
import { AutoCompleteProps, DataSourceItemType } from 'antd/es/auto-complete';
import React, { Component } from 'react';

import classNames from 'classnames';
import debounce from 'lodash/debounce';
import styles from './index.less';

export interface HeaderSearchProps {
    onPressEnter: (value: string) => void;
    onSearch: (value: string) => void;
    onChange: (value: string) => void;
    onVisibleChange: (b: boolean) => void;
    className: string;
    placeholder: string;
    defaultActiveFirstOption: boolean;
    dataSource: DataSourceItemType[];
    defaultOpen: boolean;
    open?: boolean;
    defaultValue?: string;
}

interface HeaderSearchState {
    value?: string;
    searchMode: boolean;
}

export default class HeaderSearch extends Component<HeaderSearchProps, HeaderSearchState> {
    static defaultProps = {
        defaultActiveFirstOption: false,
        onPressEnter: () => {},
        onSearch: () => {},
        onChange: () => {},
        className: '',
        placeholder: '',
        dataSource: [],
        defaultOpen: false,
        onVisibleChange: () => {}
    };

    static getDerivedStateFromProps(props: HeaderSearchProps) {
        if ('open' in props) {
            return {
                searchMode: props.open
            };
        }
        return null;
    }

    private inputRef: Input | null = null;

    constructor(props: HeaderSearchProps) {
        super(props);
        this.state = {
            searchMode: props.defaultOpen,
            value: props.defaultValue
        };
        this.debouncePressEnter = debounce(this.debouncePressEnter, 500, {
            leading: true,
            trailing: false
        });
    }

    onKeyDown = (e: React.KeyboardEvent) => {
        if (e.key === 'Enter') {
            this.debouncePressEnter();
        }
    };

    onChange: AutoCompleteProps['onChange'] = value => {
        if (typeof value === 'string') {
            const { onSearch, onChange } = this.props;
            this.setState({ value });
            if (onSearch) {
                onSearch(value);
            }
            if (onChange) {
                onChange(value);
            }
        }
    };

    enterSearchMode = () => {
        const { onVisibleChange } = this.props;
        onVisibleChange(true);
        this.setState({ searchMode: true }, () => {
            const { searchMode } = this.state;
            if (searchMode && this.inputRef) {
                this.inputRef.focus();
            }
        });
    };

    leaveSearchMode = () => {
        this.setState({
            searchMode: false
        });
    };

    debouncePressEnter = () => {
        const { onPressEnter } = this.props;
        const { value } = this.state;
        onPressEnter(value || '');
    };

    render() {
        const { className, defaultValue, placeholder, open, ...restProps } = this.props;
        const { searchMode, value } = this.state;
        delete restProps.defaultOpen; // for rc-select not affected
        const inputClass = classNames(styles.input, {
            [styles.show]: searchMode
        });

        return (
            <span
                className={classNames(className, styles.headerSearch)}
                onClick={this.enterSearchMode}
                onTransitionEnd={({ propertyName }) => {
                    if (propertyName === 'width' && !searchMode) {
                        const { onVisibleChange } = this.props;
                        onVisibleChange(searchMode);
                    }
                }}
            >
                <Icon type="search" key="Icon" />
                <AutoComplete
                    key="AutoComplete"
                    {...restProps}
                    className={inputClass}
                    value={value}
                    onChange={this.onChange}
                >
                    <Input
                        ref={node => {
                            this.inputRef = node;
                        }}
                        defaultValue={defaultValue}
                        aria-label={placeholder}
                        placeholder={placeholder}
                        onKeyDown={this.onKeyDown}
                        onBlur={this.leaveSearchMode}
                    />
                </AutoComplete>
            </span>
        );
    }
}
